package edu.unice.simul.util.graphs;

import java.util.ArrayList;
import java.util.List;

import edu.unice.simul.util.Block;

/**
 * Représente un arc dans un graphe
 * 
 * @author Romain Ciaccafava
 * 
 */
final class Arc {
	/**
	 * Sommet de destination de l'arc
	 */
	private Sommet sommetDestination;
	/**
	 * Coût d'utilisation de l'arc
	 */
	private double cout;

	public Arc(Sommet sommetDestination, double cout) {
		this.sommetDestination = sommetDestination;
		this.cout = cout;
	}

	/**
	 * Retourne le sommet de destination de larc
	 */
	public Sommet getSommetDestination() {
		return sommetDestination;
	}

	/**
	 * Retourne le coût d'utilisation de l'arc
	 */
	public double getCout() {
		return cout;
	}
}

/**
 * Représente un sommet d'un graphe
 * 
 * @author Romain Ciaccafava
 * 
 */
public class Sommet implements Comparable<Sommet> {
	/**
	 * Compteur de sommets : sert pour l'ID
	 */
	private static int nbSommets = 0;
	/**
	 * Liste des arcs sortants
	 */
	private List<Arc> arcsSortants = new ArrayList<Arc>();
	/**
	 * Block correspondant au sommet
	 */
	private Block block;
	/**
	 * ID du sommet
	 */
	private int ID;
	/**
	 * Pondération du sommet (par défaut, l'infinie)
	 */
	private double distance = Double.MAX_VALUE;

	public Sommet(Block value) {
		this.block = value;
		this.ID = Sommet.nbSommets++;
	}

	/**
	 * Ajoute l'arc aux arcs sortants du sommet
	 * 
	 * @param sommet
	 *          sommet sortant de l'arc
	 * @param cout
	 *          coût de l'arc
	 */
	public void addArc(Sommet sommet, double cout) {
		for (Arc arc : arcsSortants) {
			// Si cet arc exite déjà, on ne l'ajoute pas une nouvelle fois !
			if (arc.getSommetDestination() == sommet) {
				if (arc.getCout() == cout)
					return;
				else {
					arcsSortants.remove(arc);
					break;
				}
			}
		}
		// On ajoute l'arc dans les deux sens
		this.arcsSortants.add(new Arc(sommet, cout));
		sommet.arcsSortants.add(new Arc(this, cout));
	}

	public List<Arc> getArcsSortants() {
		return arcsSortants;
	}

	public Block getBlock() {
		return block;
	}

	/**
	 * Récupère l'ID unique du sommet
	 */
	public Integer getID() {
		return ID;
	}

	public int compareTo(Sommet sommet) {
		return (int) (this.distance * 100 - sommet.getDistance() * 100);
	}

	/**
	 * Retourne le pondération du sommet
	 */
	public double getDistance() {
		return this.distance;
	}

	/**
	 * Définie la pondération du sommet
	 */
	public void setDistance(double distance) {
		this.distance = distance;
	}

	@Override
	public String toString() {
		return this.distance + "";
	}

}
